using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Text.RegularExpressions;
using DifferenceEngine;
using System.Collections;
using GeneratorLibrary.Settings;
using System.Reflection;
using GeneratorLibrary.Client.Base;

namespace GeneratorLibrary.ClassGeneratorLibrary {
    public partial class ClassGenForm : Form {
        List<IProjectInterface> projects;
        List<string> projectFolders;
        string newFolder;
        IClientFactory factory;

        bool initialLoadFinished = false;

        private IClientFactory GetClientFactory(string generatorPath) {
            if (!String.IsNullOrEmpty(generatorPath)) {
                Type t;
                try {
                    //possible TypeLoadException
                    t = Type.GetType(generatorPath, false, false);

                    //possible InvalidCastException. 
                    return (IClientFactory)Activator.CreateInstance(t);

                } catch (TypeLoadException ex) {
                    throw new Exception("Selected 'Class Generator Type' not found", ex);
                } catch (InvalidCastException ex) {
                    throw new Exception("Selected 'Class Generator Type' does not implement IClientFactory.", ex);
                } catch (Exception ex) {
                    throw new Exception("Selected 'Class Generator Type' through an error during GetType or during Instantiation.", ex);
                }
            } else if (factory == null) {
                //this "can't" actually happen since we force there to be a default in the settings...
                // unless they manually change their settings file.
                throw new Exception("No default 'Class Generator Type' has been set.");
            } else {
                //they passed in blank, so we won't change it.
                return factory;
            }
        }



        public string NewFolder {
            get { return newFolder; }
            set { newFolder = value; }
        }

        public ClassGenForm(List<IProjectInterface> projects) {
            SettingsHelper.Initialize();

            InitializeComponent();
            this.projects = projects;

            projectFolders = new List<string>(projects.Count);
            foreach (IProjectInterface p in projects) {
                string directory = p.Directory;
                projectFolders.Add(new DirectoryInfo(directory).FullName);
            }
            bool allowOverride = projects[0].AllowOverrideNamespace;
            lblNamespace.Visible = allowOverride;
            cboNamespace.Visible = allowOverride;
        }

        private void Form1_Load(object sender, EventArgs e) {
            LoadFactoryList();
            LoadAddReferenceList();

            foreach (string str in projectFolders) {
                DirectoryInfo dir = new DirectoryInfo(str);
                TreeNode node = new TreeNode(dir.Name);
                tvFile.Nodes.Add(node);
                LoadChildren(dir, node);
                FindDac(dir);
            }
            if (this.projects.Count == 1) {
                tvFile.Nodes[0].Expand();
            }
            txtServer.DataSource = Addin.Default["DatabaseServerList"].ToString().Split(new char[] { ',' });
            txtServer.Text = Addin.Default["DatabaseServer"].ToString();

            bindDatabases(false);

            initialLoadFinished = true;
        }



        private void LoadFactoryList() {
            List<KeyValuePair<string, string>> factories = new List<KeyValuePair<string, string>>();
            string[] ary = Addin.Default.ClassGenerators.Split(new char[] { ',' });
            foreach (string item in ary) {
                string[] pair = item.Split(new char[] { '=' });
                factories.Add(new KeyValuePair<string, string>(pair[1].Trim(), pair[0].Trim()));
            }
            ddlFactory.DisplayMember = "Value";
            ddlFactory.ValueMember = "Key";
            ddlFactory.DataSource = factories;

            factory = GetClientFactory(Addin.Default.DefaultClassGenerator);
            ddlFactory.SelectedValue = Addin.Default.DefaultClassGenerator;
        }

        private void LoadChildren(DirectoryInfo parentDir, TreeNode parent) {
            foreach (DirectoryInfo dir in parentDir.GetDirectories()) {
                TreeNode node = new TreeNode(dir.Name);
                parent.Nodes.Add(node);
                LoadChildren(dir, node);
                FindDac(dir);
            }
            foreach (FileInfo file in parentDir.GetFiles()) {
                TreeNode node = new TreeNode(file.Name);
                node.ImageIndex = 1;
                node.SelectedImageIndex = 1;
                parent.Nodes.Add(node);
            }
        }

        string dacNamespace = null;
        private void FindDac(DirectoryInfo dir) {
            if (dacNamespace == null) {
                foreach (FileInfo file in dir.GetFiles("*.cs")) {
                    if (file.Name.EndsWith(".aspx.cs"))
                        continue;
                    if (file.Name == "DAC.cs" || file.Name == "DAL.cs") {
                        using (StreamReader r = new StreamReader(file.FullName)) {
                            string str = r.ReadToEnd();
                            Regex regex = new Regex("namespace\\s+(\\S+)\\s*{");
                            Match m = regex.Match(str);
                            if (m != null)
                                dacNamespace = m.Groups[0].Value;
                            //Regex regex = ": StandardSqlDac"
                        }
                    }
                }
            }
        }

        private void btnNewFolder_Click(object sender, EventArgs e) {
            TreeNode selected = tvFile.SelectedNode;
            if (selected != null) {
                NewFolder = "";
                PromptBox box = new PromptBox("New Folder Name:");
                DialogResult result = box.ShowDialog();
                NewFolder = box.InputText;
                if (result == DialogResult.OK && NewFolder.Length > 0) {
                    List<string> path = new List<string>();
                    TreeNode temp = selected;

                    //directories can't go under files
                    if (selected.ImageIndex == 1)
                        selected = selected.Parent;

                    while (temp.Level > 0) {
                        path.Insert(0, temp.Text);
                        temp = temp.Parent;
                    }
                    projects[temp.Index].AddFolder(NewFolder, path);

                    selected.Nodes.Clear();
                    LoadChildren(new DirectoryInfo(GetPath(selected)), selected);

                    if (!selected.IsExpanded)
                        selected.Expand();
                }
            } else {
                MessageBox.Show("Please select the parent folder first.");
            }
        }

        private string GetPath(TreeNode node) {
            if (node.Parent == null) {
                return projectFolders[node.Index];
            } else {
                return GetPath(node.Parent) + @"\" + node.Text;
            }
        }

        private void bindDatabases(bool showError) {
            try {
                tvDatabase.Nodes.Clear();

                if (String.IsNullOrEmpty(txtServer.Text))
                    return;

                BaseDAC dac = factory.NewClassGenDAC(GetConnectionString(factory.CatalogSchema), factory.CatalogSchema);
                foreach (string str in dac.GetDatabases()) {
                    TreeNode node = new TreeNode(str);
                    tvDatabase.Nodes.Add(node);
                    node.Nodes.Add("###");
                }

                List<string> DatabaseServerList = new List<string>(Addin.Default["DatabaseServerList"].ToString().Split(new char[] { ',' }));
                if (!DatabaseServerList.Contains(txtServer.Text)) {
                    DatabaseServerList.Add(txtServer.Text);
                    DatabaseServerList.Sort();
                    Addin.Default["DatabaseServerList"] = String.Join(",", DatabaseServerList.ToArray());
                    Addin.Default.Save();
                    string oldserver = txtServer.Text;
                    txtServer.DataSource = DatabaseServerList;
                    txtServer.Text = oldserver;
                }
            } catch (Exception ex) {
                if (showError)
                    MessageBox.Show("Login Failed: " + ex.Message, "Login Failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        private string GetConnectionString(string db) {
            if (chkIntegratedSecurity.Checked) {
                return factory.GetConnectionString(this.txtServer.Text, db);
            } else {
                return factory.GetConnectionString(this.txtServer.Text, db, txtUserName.Text, txtPassword.Text);
            }
        }

        private void LoadTables(TreeNode parent) {
            BaseDAC dac = factory.NewClassGenDAC(GetConnectionString(parent.Text), parent.Text);
            TreeNode tableNode = new TreeNode("Tables");
            TreeNode viewNode = new TreeNode("Views");
            parent.Nodes.Add(tableNode);
            parent.Nodes.Add(viewNode);

            foreach (string str in dac.GetTables()) {
                TreeNode node = new TreeNode(str);
                node.ImageIndex = 1;
                node.SelectedImageIndex = 1;
                tableNode.Nodes.Add(node);
            }
            foreach (string str in dac.GetViews()) {
                TreeNode node = new TreeNode(str);
                node.ImageIndex = 1;
                node.SelectedImageIndex = 1;
                viewNode.Nodes.Add(node);
            }
        }


        private void tvFile_DragEnter(object sender, DragEventArgs e) {
            e.Effect = DragDropEffects.Move;

        }

        private void tvFile_DragDrop(object sender, DragEventArgs e) {
            if (e.Data.GetDataPresent("CodersLab.Windows.Controls.NodesCollection", false)) {
                Point pt = ((TreeView)sender).PointToClient(new Point(e.X, e.Y));
                TreeNode DestinationNode = ((TreeView)sender).GetNodeAt(pt);

                if (DestinationNode.ImageIndex == 1)//it's a file
                    DestinationNode = DestinationNode.Parent;

                CodersLab.Windows.Controls.NodesCollection NewNodes =
                    (CodersLab.Windows.Controls.NodesCollection)e.Data.GetData("CodersLab.Windows.Controls.NodesCollection");

                if (DestinationNode.TreeView != NewNodes[0].TreeView && NewNodes[0].Level > 0) {
                    string path = GetPath(DestinationNode);
                    string classNamespace = getClassNamespace(DestinationNode);

                    string errorList = "";
                    foreach (TreeNode NewNode in NewNodes) {
                        string table = NewNode.Text;
                        TreeNode temp = NewNode.Parent;
                        while (temp.Level > 0) {
                            temp = temp.Parent;
                        }
                        string database = temp.Text;
                        try {
                            if (NewNode.Level == 2) {
                                GenerateClasses(database, table, path, classNamespace, DestinationNode);
                            } else {
                                foreach (TreeNode node in NewNode.Nodes) {
                                    table = node.Text;
                                    try {
                                        GenerateClasses(database, table, path, classNamespace, DestinationNode);
                                    } catch {
                                        errorList += table + ".cs could not be generated." + Environment.NewLine;
                                    }
                                }
                            }
                        } catch {
                            errorList += table + ".cs could not be generated." + Environment.NewLine;
                        }
                    }
                    if (!String.IsNullOrEmpty(errorList))
                        MessageBox.Show(errorList);

                    DestinationNode.Nodes.Clear();
                    LoadChildren(new DirectoryInfo(GetPath(DestinationNode)), DestinationNode);
                    if (!DestinationNode.IsExpanded)
                        DestinationNode.Expand();
                }
            }
        }

        private string getClassNamespace(TreeNode node) {
            string retValue = "", path = "";
            while (node.Level > 0) {
                retValue = node.Text + "." + retValue;
                path = node.Text + "\\" + path;
                node = node.Parent;
            }
            path = projects[node.Index].Directory + "\\" + path;

            if (retValue.StartsWith("App_Code."))
                retValue = retValue.Remove(0, 9);

            if (retValue.Length > 0)
                retValue = retValue.Remove(retValue.Length - 1);


            string root = "";
            if (cboNamespace.Visible && cboNamespace.Text != "--NO OVERRIDE--" && cboNamespace.Text.Length > 0) {
                root = cboNamespace.Text.Replace("--BLANK NAMESPACE--", "");
            } else {
                try {
                    //Addin sometimes throws errors...
                    //selecting a node that doesn't exist throws an error. Enumerating through nodes throws an error.
                    //There isn't a ContainsIndex() method... (looking at com objects causes them to throw errors)
                    root = projects[node.Index].GetRootNameSpace(path);
                } catch {
                    root = "";
                }
            }

            if (root.Length > 0) {
                if (retValue.Length > 0)
                    return root + "." + retValue;
                else
                    return root;
            } else {
                return "";
            }
        }

        private void GenerateClasses(string database, string table, string path, string classNamespace, TreeNode parent) {
            BaseDAC dac = factory.NewClassGenDAC(GetConnectionString(database), database);
            DataTable dt = dac.GetColumns(table);

            ClassBase dc;
            try {
                dc = factory.NewDataClass(dt, table, classNamespace, dacNamespace, factory.GetDefaultDACName(txtServer.Text, database));
            } catch (Exception ex) {
                MessageBox.Show("The class '" + table + ".cs' could not be produced. Error Details: " + ex.Message);
                return;
            }
            string fileName = path + @"\" + table + ".cs";

            if (new FileInfo(fileName).Exists) {
                DiffList_Text sLF = new DiffList_TextFile(fileName);
                DiffList_Text dLF = new DiffList_TextString(dc.WriteString());

                DiffEngine de = new DiffEngine();
                de.ProcessDiff(sLF, dLF, DiffEngineLevel.SlowPerfect);

                ArrayList rep = de.DiffReport();
                DiffResolver dlg = new DiffResolver(sLF, dLF, rep);
                DialogResult result = dlg.ShowDialog();

                if (result == DialogResult.OK) {
                    string newFile = dlg.GetSourceLines();

                    string tempFile = Path.GetTempFileName();
                    new FileInfo(fileName).CopyTo(tempFile, true);
                    new FileInfo(fileName).Delete();

                    using (StreamWriter w = new StreamWriter(fileName)) {
                        w.Write(dlg.GetSourceLines());
                    }
                }
                dlg.Dispose();
            } else {
                dc.WriteNewFile(fileName);

                List<string> pathList = new List<string>();
                TreeNode temp = parent;
                while (temp.Level > 0) {
                    pathList.Insert(0, temp.Text);
                    temp = temp.Parent;
                }
                projects[temp.Index].AddFromFile(pathList, path + @"\" + table + ".cs");
            }
        }
        private void tvDatabase_ItemDrag(object sender, ItemDragEventArgs e) {
            DoDragDrop(e.Item, DragDropEffects.Move);
        }

        private void tvDatabase_BeforeExpand(object sender, TreeViewCancelEventArgs e) {
            if (e.Node.Nodes.Count == 1 && e.Node.Nodes[0].Text == "###") {
                e.Node.Nodes.Clear();
                LoadTables(e.Node);
            }
        }

        private void btnRefreshProjects_Click(object sender, EventArgs e) {
            for (int i = 0; i < projectFolders.Count; i++) {
                DirectoryInfo dir = new DirectoryInfo(projectFolders[i]);
                tvFile.Nodes[i].Nodes.Clear();
                LoadChildren(dir, tvFile.Nodes[i]);
            }
        }

        private void btnRefreshDB_Click(object sender, EventArgs e) {
            bindDatabases(true);
        }
        #region Database Treeview --> Copy / Refresh
        private void dbRefreshToolStripMenuItem_Click(object sender, EventArgs e) {
            if (tvDatabase.SelectedNodes == null || tvDatabase.SelectedNodes.Count == 0)
                return;

            foreach (TreeNode node in tvDatabase.SelectedNodes) {
                TreeNode test = node;
                if (test.Level == 1)
                    test = node.Parent;
                else if (test.Level == 2)
                    test = node.Parent.Parent;

                if (test.IsExpanded) {
                    bool tables = test.Nodes[0].IsExpanded;
                    bool views = test.Nodes[1].IsExpanded;
                    test.Nodes.Clear();
                    LoadTables(test);
                    if (tables)
                        test.Nodes[0].Expand();
                    if (views)
                        test.Nodes[1].Expand();
                } else {
                    test.Nodes.Clear();
                    test.Nodes.Add("###");
                }
            }
        }
        private void copyFullNameToolStripMenuItem_Click(object sender, EventArgs e) {
            StringBuilder sb = new StringBuilder();
            if (tvDatabase.SelectedNodes == null || tvDatabase.SelectedNodes.Count == 0)
                return;

            int level = tvDatabase.SelectedNodes[0].Level;
            foreach (TreeNode node in Sort(tvDatabase.SelectedNodes)) {
                TreeNode temp = node;
                while (temp.Level > 1) {
                    temp = temp.Parent;
                }
                sb.Append(temp.Text);
                if (level == 2)
                    sb.AppendLine(".." + node.Text);
                else if (level == 2)
                    sb.AppendLine("->" + node.Text);
                else
                    sb.AppendLine();
            }
            doCopy(sb.ToString());
        }
        private void copyToolStripMenuItem_Click(object sender, EventArgs e) {
            StringBuilder sb = new StringBuilder();
            if (tvDatabase.SelectedNodes == null || tvDatabase.SelectedNodes.Count == 0)
                return;

            int level = tvDatabase.SelectedNodes[0].Level;
            foreach (TreeNode node in Sort(tvDatabase.SelectedNodes)) {
                sb.AppendLine(node.Text);
            }
            doCopy(sb.ToString());
        }

        private void copyChildrenToolStripMenuItem_Click(object sender, EventArgs e) {
            StringBuilder sb = new StringBuilder();
            if (tvDatabase.SelectedNodes == null || tvDatabase.SelectedNodes.Count == 0)
                return;

            CopyDBChildren(sb, "", Sort(tvDatabase.SelectedNodes));

            doCopy(sb.ToString());
        }

        private void CopyDBChildren(StringBuilder sb, string prefix, IList nodesCollection) {
            if (nodesCollection == null || nodesCollection.Count == 0)
                return;

            int level = ((TreeNode)nodesCollection[0]).Level;
            foreach (TreeNode node in nodesCollection) {
                if (level == 0) {
                    prefix = node.Text + "..";
                    if (node.Nodes.Count == 1) {
                        node.Nodes.Clear();
                        LoadTables(node);
                    }
                } else if (level == 1 && String.IsNullOrEmpty(prefix)) {
                    prefix = node.Parent.Text + "..";
                }
                if (level == 2) {
                    sb.AppendLine(prefix + node.Text);
                } else {
                    CopyDBChildren(sb, prefix, node.Nodes);
                }
            }
        }
        private void tvDatabase_KeyUp(object sender, KeyEventArgs e) {
            if (e.Control && !e.Alt && !e.Shift && e.KeyValue == 67) {
                copyToolStripMenuItem_Click(sender, e);
            }
        }
        #endregion
        #region File Treeview --> Copy / Refresh / RightClickSelect
        private void tvFile_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e) {
            //causes right click to select
            tvFile.SelectedNode = e.Node;
        }
        private void fileRefreshToolStripMenuItem_Click(object sender, EventArgs e) {
            TreeNode node = tvFile.SelectedNode;
            if (node == null)
                return;

            string selectNode = null;
            if (node.ImageIndex == 1) {
                selectNode = node.Text;
                node = node.Parent;
            }

            node.Nodes.Clear();
            LoadChildren(new DirectoryInfo(GetPath(node)), node);
            if (!node.IsExpanded)
                node.Expand();

            if (selectNode != null) {
                foreach (TreeNode child in node.Nodes) {
                    if (child.Text == selectNode) {
                        tvFile.SelectedNode = child;
                        break;
                    }
                }
            }
        }
        private void copyPathToolStripMenuItem_Click(object sender, EventArgs e) {
            doCopy(GetPath(tvFile.SelectedNode) + Environment.NewLine);
        }

        private void copyNameToolStripMenuItem_Click(object sender, EventArgs e) {
            doCopy(tvFile.SelectedNode.Text + Environment.NewLine);
        }
        private void tvFile_KeyUp(object sender, KeyEventArgs e) {
            if (e.Control && !e.Alt && !e.Shift && e.KeyCode == Keys.C) {
                copyPathToolStripMenuItem_Click(sender, e);//CTRL-C
            } else if (e.Control && !e.Alt && e.Shift && e.KeyCode == Keys.C) {
                copyNameToolStripMenuItem_Click(sender, e);//CTRL-SHIFT-C
            } else if (!e.Control && !e.Alt && !e.Shift && e.KeyCode == Keys.Delete) {
                deleteToolStripMenuItem_Click(sender, e);//Delete
            } else if (e.Control && !e.Alt && !e.Shift && e.KeyCode == Keys.Enter) {
                exploreToolStripMenuItem_Click(sender, e);//CTRL-Enter
            } else if (!e.Control && !e.Alt && !e.Shift && e.KeyCode == Keys.Enter) {
                //Enter Key
                TimeSpan span = DateTime.Now.Subtract(lastDelete);
                if (tvFile.SelectedNode != null && span.TotalSeconds > 1)
                    tvFile.SelectedNode.Toggle();
            }
        }
        DateTime lastDelete = DateTime.Now;
        private void deleteToolStripMenuItem_Click(object sender, EventArgs e) {
            lastDelete = DateTime.Now;
            if (tvFile.SelectedNode != null && MessageBox.Show("Are you sure you wish to delete this item? (No undo!)", "Delete Confirmation", MessageBoxButtons.OKCancel) == DialogResult.OK) {
                List<string> pathList = new List<string>();
                TreeNode temp = tvFile.SelectedNode.Parent;
                while (temp.Level > 0) {
                    pathList.Insert(0, temp.Text);
                    temp = temp.Parent;
                }

                if (tvFile.SelectedNode.ImageIndex == 1) {
                    projects[temp.Index].DeleteFile(pathList, tvFile.SelectedNode.Text);
                } else {
                    projects[temp.Index].DeleteFolder(pathList, tvFile.SelectedNode.Text);
                }

                tvFile.SelectedNode.Remove();
            }
        }

        private void exploreToolStripMenuItem_Click(object sender, EventArgs e) {
            if (tvFile.SelectedNode != null) {
                string args;
                if (tvFile.SelectedNode.ImageIndex == 1) {
                    string path = GetPath(tvFile.SelectedNode.Parent);
                    args = " /e,\"" + path + "\",/select,\"" + path + "\\" + tvFile.SelectedNode.Text + "\"";
                } else {
                    args = " /e,\"" + GetPath(tvFile.SelectedNode) + "\"";
                }

                System.Diagnostics.Process.Start("explorer", args);
            }
        }
        #endregion
        #region Copy --> to Clipboard
        private void doCopy(string p) {
            Clipboard.SetText(p, TextDataFormat.Text);
            System.Media.SystemSounds.Asterisk.Play();
            Color c = this.BackColor;
            this.BackColor = Color.Green;
            this.BackColor = c;

        }
        #endregion
        #region Sorting CodersLab.Windows.Controls.NodesCollection
        private class SortedTreeNodes : KeyedCollection<decimal, TreeNode> {
            protected override decimal GetKeyForItem(TreeNode item) {
                //assumes that there's less than 10,000 tables and less than 10,000 views in any 1 database.
                //if that's not true, then you might try reorganizing your database you friggen fruitcake.
                TreeNode temp = item;
                decimal sort = 0;
                while (temp != null) {
                    if (temp.Level == 0) {
                        sort += temp.Index * 10;
                    } else if (temp.Level == 1) {
                        sort += temp.Index;
                    } else {
                        sort += (((decimal)temp.Index) / 10000);
                    }
                    temp = temp.Parent;
                }
                return sort;
            }
            public ICollection<decimal> GetKeys() {
                decimal[] array = new decimal[this.Dictionary.Keys.Count];
                this.Dictionary.Keys.CopyTo(array, 0);
                Array.Sort(array);
                return array;
            }
        }
        private List<TreeNode> Sort(CodersLab.Windows.Controls.NodesCollection nodesCollection) {
            SortedTreeNodes nodes = new SortedTreeNodes();
            foreach (TreeNode node in nodesCollection) {
                nodes.Add(node);
            }
            List<TreeNode> list = new List<TreeNode>();
            foreach (decimal d in nodes.GetKeys()) {
                list.Add(nodes[d]);
            }
            return list;
        }
        #endregion

        private void btnSettings_Click(object sender, EventArgs e) {
            ChangeSettings form = new ChangeSettings();
            form.ShowDialog();
        }

        private void btnAddDac_Click(object sender, EventArgs e) {
            try {
                TreeNode selected = tvFile.SelectedNode;
                if (selected != null) {
                    string db = "";
                    if (tvDatabase.SelectedNodes.Count > 0) {
                        TreeNode tempNode = tvDatabase.SelectedNodes[0];
                        while (tempNode.Parent != null) {
                            tempNode = tempNode.Parent;
                        }
                        db = tempNode.Text;
                    }
                    string className = factory.GetDefaultDACName(txtServer.Text,  db);
                    string path = GetPath(selected) + @"\" + className;
                    string path2 = ".cs";
                    int i = 1;
                    //write file here
                    while (new FileInfo(path + path2).Exists) {
                        i++;
                        path2 = i.ToString() + ".cs";
                    }

                    CopyManifestResourceClass(path + path2, factory.getEmpeddedResourceOutputDAC_Path(), getClassNamespace(selected), chkDacExamples.Checked, className);

                    List<string> pathList = new List<string>();
                    TreeNode temp = selected;
                    while (temp.Level > 0) {
                        pathList.Insert(0, temp.Text);
                        temp = temp.Parent;
                    }
                    projects[temp.Index].AddFromFile(pathList, path + path2);

                    selected.Nodes.Clear();
                    LoadChildren(new DirectoryInfo(GetPath(selected)), selected);

                    if (!selected.IsExpanded)
                        selected.Expand();
                }
            } catch (Exception ex) {
                MessageBox.Show("Error occurred: " + ex.Message);
            }
        }
        private static void CopyManifestResourceClass(string path, string manifestResource, string inNamespace) {
            CopyManifestResourceClass(path, manifestResource, inNamespace, null, null);
        }
        private static void CopyManifestResourceClass(string path, string manifestResource, string inNamespace, bool? showExamples, string className) {
            using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(manifestResource)) {
                using (StreamReader r = new StreamReader(stream)) {
                    using (StreamWriter w = new StreamWriter(path)) {
                        string s = r.ReadToEnd();
                        if (inNamespace == "") {
                            s = s.Replace("#NAMESPACE_BEGIN#", "");
                            s = s.Replace("#NAMESPACE_END#", "");
                        } else {
                            s = s.Replace("#NAMESPACE_BEGIN#", "namespace " + inNamespace + " {");
                            s = s.Replace("#NAMESPACE_END#", "}");
                        }
                        if (showExamples != null) {
                            if (showExamples.Value) {//remove the template names
                                s = s.Replace("#EXAMPLES_BEGIN#", "");
                                s = s.Replace("#EXAMPLES_END#", "");
                            } else {//remove the whole section
                                int start = s.IndexOf("#EXAMPLES_BEGIN#");
                                if (start >= 0) {
                                    int end = s.IndexOf("#EXAMPLES_END#", start);
                                    if (start < end) {
                                        int length = end - start + "#EXAMPLES_END#".Length;
                                        s = s.Remove(start, length);
                                    }
                                }
                            }
                        }
                        if (!String.IsNullOrEmpty(className)) {
                            s = s.Replace("#CLASS_NAME#", className);
                        }
                        w.Write(s);
                    }
                }
            }
        }

        private void btnLogin_Click(object sender, EventArgs e) {
            this.Cursor = Cursors.WaitCursor;
            if (txtServer.Text.Length > 0) {
                bindDatabases(true);
            }
            btnLogin.ForeColor = Color.Black;
            btnLogin.Font = new Font(btnLogin.Font, FontStyle.Regular);
            this.Cursor = Cursors.Default;
        }

        private void txtServer_SelectedIndexChanged(object sender, EventArgs e) {
            btnLogin.ForeColor = Color.Red;
            btnLogin.Font = new Font(btnLogin.Font, FontStyle.Italic);
        }

        private void ddlFactory_SelectedIndexChanged(object sender, EventArgs e) {
            if (initialLoadFinished) {
                string factoryType = ddlFactory.SelectedValue.ToString();
                if (factoryType != factory.GetType().FullName) {
                    factory = GetClientFactory(factoryType);
                    tvDatabase.Nodes.Clear();
                    txtServer.Text = "";
                }
            }
        }



        private void LoadAddReferenceList() {
            bool isRef = false;
            foreach (IProjectInterface p in projects) {
                if (p is IReferenceSettingProject) {
                    isRef = true;
                    break;
                }
            }
            if (!isRef) {
                ddlAddReference.Visible = false;
                return;
            }
            List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();
            string[] ary = Addin.Default.AddReferenceList.Split(new char[] { ';' });
            list.Add(new KeyValuePair<string, string>("--Add Reference--", "--Add Reference--"));
            foreach (string item in ary) {
                string[] pair = item.Split(new char[] { '=' });
                list.Add(new KeyValuePair<string, string>(pair[1].Trim(), pair[0].Trim()));
            }
            ddlAddReference.DisplayMember = "Value";
            ddlAddReference.ValueMember = "Key";
            ddlAddReference.DataSource = list;
        }

        private void ddlAddReference_SelectedIndexChanged(object sender, EventArgs e) {
            if (ddlAddReference.SelectedIndex > 0) {
                if (tvFile.SelectedNode == null) {
                    MessageBox.Show("You must select a project (on right) to add the reference to.");
                    return;
                }

                TreeNode node = tvFile.SelectedNode;
                while (node.Parent != null) {
                    node = node.Parent;
                }

                if (projects[node.Index] is IReferenceSettingProject && ((IReferenceSettingProject)projects[node.Index]).AllowsReferences()) {
                    try {
                        ((IReferenceSettingProject)projects[node.Index]).AddReference(ddlAddReference.SelectedText, ddlAddReference.SelectedValue.ToString());
                    } catch (Exception ex) {
                        MessageBox.Show("Error occurred: " + ex.Message);
                    }
                } else {
                    MessageBox.Show("The selected project does not allow for setting reference.");
                }
            }
        }

        private void btnViewReferences_Click(object sender, EventArgs e) {
            if (tvFile.SelectedNode == null) {
                MessageBox.Show("You must select a project (on right) to add the reference to.");
                return;
            }

            TreeNode node = tvFile.SelectedNode;
            while (node.Parent != null) {
                node = node.Parent;
            }
            if (projects[node.Index] is IReferenceSettingProject && ((IReferenceSettingProject)projects[node.Index]).AllowsReferences()) {
                new ViewReferences((IReferenceSettingProject)projects[node.Index]).ShowDialog();
            } else {
                MessageBox.Show("The selected project does not allow for setting reference.");
            }
        }
    }
}